5.3 Daten filtern und gruppieren#
Im vorherigen Kapitel haben wir Autos basierend auf ihrem Kilometerstand gruppiert und visualisiert. Während diese Gruppierung automatisch im Hintergrund stattfand, werden wir in diesem Kapitel lernen, wie wir direkt auf die gruppierten Daten zugreifen und zusätzliche Analysen durchführen können.
Lernziele#
Lernziele
Sie wissen, dass die Wahrheitswerte
True(wahr) oderFalse(falsch) in dem Datentyp bool gespeichert werden.Sie kennen die wichtigsten Vergleichsoperatoren (
<,<=,>,>=,==,!=,in,not in) in Python.Sie können ein Pandas-DataFrame-Objekt nach einem Wert filtern.
Sie können ein Pandas-DataFrame-Objekt mit den Methoden
groupby()undget_group()gruppieren.
Daten filtern#
Im vorherigen Kapitel haben wir die Kilometerstände von Autos untersucht, die im Jahr 2020 zugelassen und Mitte 2023 auf Autoscout24.de angeboten wurden. Bei der Kategorisierung der Kilometerstände fiel auf, dass Fahrzeuge mit einer Laufleistung von über 200000 km selten sind. Trotzdem beeinflusste dies die Aufteilung in zehn gleichmäßige Gruppen, die von 0 km bis 435909 km reichten, erheblich. Um eine genauere Analyse zu ermöglichen, wäre es sinnvoll, Fahrzeuge mit einer Laufleistung von bis zu 200.000 km in den Fokus zu nehmen und die Ausreißer auszuschließen. Daher widmen wir uns in diesem Kapitel der Filterung von tabellarischen Datensätzen mithilfe von Pandas.
Zuerst laden wir den Datensatz autoscout24_DE_2020.csv und
überprüfen den Inhalt.
import pandas as pd
url = 'https://gramschs.github.io/book_ml4ing/data/autoscout24_DE_2020.csv'
data = pd.read_csv(url)
data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 18566 entries, 0 to 18565
Data columns (total 14 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Marke 18566 non-null object
1 Modell 18566 non-null object
2 Farbe 18546 non-null object
3 Erstzulassung 18566 non-null object
4 Jahr 18566 non-null int64
5 Preis (Euro) 18566 non-null int64
6 Leistung (kW) 18552 non-null float64
7 Leistung (PS) 18552 non-null float64
8 Getriebe 18566 non-null object
9 Kraftstoff 18566 non-null object
10 Verbrauch (l/100 km) 15501 non-null object
11 Verbrauch (g/km) 18566 non-null object
12 Kilometerstand (km) 18566 non-null float64
13 Bemerkungen 18566 non-null object
dtypes: float64(3), int64(2), object(9)
memory usage: 2.0+ MB
Um die Autos mit einem Kilometerstand von bis zu 200000 km zu filtern,
vergleichen wir die entsprechende Spalte mit dem Wert 200000, indem wir den aus
der Mathematik bekannten Kleiner-gleich-Operator <= benutzen. Das Ergebnis
dieses Vergleichs speichern wir in der Variable bedingung_kilometerstand.
bedingung_kilometerstand = data['Kilometerstand (km)'] <= 200000
Aber was genau ist in der Variable bedingung_kilometerstand enthalten? Schauen
wir uns den Datentyp an:
type(bedingung_kilometerstand)
pandas.core.series.Series
Offensichtlich handelt es sich um ein Pandas-Series-Objekt. Für weitere
Informationen können wir die .info()-Methode aufrufen:
bedingung_kilometerstand.info()
<class 'pandas.core.series.Series'>
RangeIndex: 18566 entries, 0 to 18565
Series name: Kilometerstand (km)
Non-Null Count Dtype
-------------- -----
18566 non-null bool
dtypes: bool(1)
memory usage: 18.3 KB
In dem Series-Objekt sind 18566 Einträge vom Datentyp bool gespeichert. Diesen
Datentyp haben wir bisher nicht kennengelernt. Wir lassen die ersten fünf
Einträge ausgeben:
bedingung_kilometerstand.head()
0 True
1 True
2 True
3 True
4 True
Name: Kilometerstand (km), dtype: bool
Sind alle Einträge mit dem Wert True gefüllt? Wie viele und vor allem welche
einzigartige Einträge gibt es in diesem Series-Objekt?
bedingung_kilometerstand.unique()
array([ True, False])
Das Series-Objekt enthält nur True und False, was den Datentyp bool
charakterisiert. In diesem Datentyp können nur zwei verschiedene Werte
gespeichert werden, nämlich wahr (True) und falsch (False). Oft sind
Wahrheitswerte das Ergebnis eines Vergleichs, wie das folgende Code-Beispiel
zeigt:
x = 19
print(x < 100)
True
In der Python-Programmierung wird der Datentyp bool oft verwendet, um
Programmcode zu verzweigen. Damit ist gemeint, dass Teile des Programms nur
durchlaufen und ausgeführt werden, wenn eine bestimmte Bedingung wahr (True)
ist. In dieser Vorlesung benutzen wir bool-Werte hauptsächlich zum Filtern von
Daten.
Welche Vergleichsoperatoren kennt Python?
In Python können die mathematischen Vergleichsoperatoren in ihrer gewohnten Schreibweise verwendet werden:
<kleiner als<=kleiner als oder gleich>größer als>=größer als oder gleich==gleich (=ist der Zuweisungsoperator, nicht mit Gleichheit verwechseln!)!=ungleich
Darüber hinaus kann mit in oder not in getestet werden, ob
ein Element in einer Liste ist oder eben nicht.
Aber was machen wir jetzt mit diesem Series-Objekt? Wir können es als Index
benutzen für den ursprünglichen Datensatz benutzen. Die Zeilen, in denen True
steht, werden übernommen, die anderen verworfen.
autos_bis_200000km = data[bedingung_kilometerstand]
autos_bis_200000km.info()
<class 'pandas.core.frame.DataFrame'>
Index: 18525 entries, 0 to 18565
Data columns (total 14 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Marke 18525 non-null object
1 Modell 18525 non-null object
2 Farbe 18505 non-null object
3 Erstzulassung 18525 non-null object
4 Jahr 18525 non-null int64
5 Preis (Euro) 18525 non-null int64
6 Leistung (kW) 18511 non-null float64
7 Leistung (PS) 18511 non-null float64
8 Getriebe 18525 non-null object
9 Kraftstoff 18525 non-null object
10 Verbrauch (l/100 km) 15472 non-null object
11 Verbrauch (g/km) 18525 non-null object
12 Kilometerstand (km) 18525 non-null float64
13 Bemerkungen 18525 non-null object
dtypes: float64(3), int64(2), object(9)
memory usage: 2.1+ MB
Von den 18566 Autos wurden 18525 Autos übernommen. Ist denn die Filterung
geglückt? Wir verschaffen uns mit der .describe()-Methode einen schnellen
Überblick.
autos_bis_200000km.describe()
| Jahr | Preis (Euro) | Leistung (kW) | Leistung (PS) | Kilometerstand (km) | |
|---|---|---|---|---|---|
| count | 18525.0 | 18525.000000 | 18511.000000 | 18511.000000 | 18525.000000 |
| mean | 2020.0 | 33513.975816 | 135.327697 | 184.079466 | 42251.647935 |
| std | 0.0 | 37458.475775 | 75.548942 | 102.680858 | 28741.442712 |
| min | 2020.0 | 5950.000000 | 4.000000 | 5.000000 | 0.000000 |
| 25% | 2020.0 | 19990.000000 | 90.000000 | 122.000000 | 22720.000000 |
| 50% | 2020.0 | 26489.000000 | 110.000000 | 150.000000 | 35722.000000 |
| 75% | 2020.0 | 35490.000000 | 148.000000 | 201.000000 | 54422.000000 |
| max | 2020.0 | 959980.000000 | 596.000000 | 810.000000 | 199000.000000 |
Der maximale Eintrag für die Spalte Kilometerstand (km) ist 199000 km. Mit dem
Tilde-Operator ~ können wir das Pandas-Series-Objekt
bedingung_kilometerstand in das Gegenteil umwandeln. Damit können wir also die
Autos mit einem Kilometerstand über 200.000 km herausfiltern.
autos_ab_200000km = data[~bedingung_kilometerstand]
autos_ab_200000km.info()
<class 'pandas.core.frame.DataFrame'>
Index: 41 entries, 968 to 18517
Data columns (total 14 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Marke 41 non-null object
1 Modell 41 non-null object
2 Farbe 41 non-null object
3 Erstzulassung 41 non-null object
4 Jahr 41 non-null int64
5 Preis (Euro) 41 non-null int64
6 Leistung (kW) 41 non-null float64
7 Leistung (PS) 41 non-null float64
8 Getriebe 41 non-null object
9 Kraftstoff 41 non-null object
10 Verbrauch (l/100 km) 29 non-null object
11 Verbrauch (g/km) 41 non-null object
12 Kilometerstand (km) 41 non-null float64
13 Bemerkungen 41 non-null object
dtypes: float64(3), int64(2), object(9)
memory usage: 4.8+ KB
41 Autos, die 2020 zugelassen wurden, sollten Mitte 2023 mit einem Kilometerstand von mehr als 200000 km verkauft werden. Schauen wir uns die Statistik an.
autos_ab_200000km.describe()
| Jahr | Preis (Euro) | Leistung (kW) | Leistung (PS) | Kilometerstand (km) | |
|---|---|---|---|---|---|
| count | 41.0 | 41.000000 | 41.000000 | 41.000000 | 41.000000 |
| mean | 2020.0 | 20958.926829 | 115.463415 | 156.975610 | 245033.951220 |
| std | 0.0 | 8955.785235 | 40.915216 | 55.554247 | 53031.305157 |
| min | 2020.0 | 8000.000000 | 56.000000 | 76.000000 | 201000.000000 |
| 25% | 2020.0 | 15740.000000 | 85.000000 | 116.000000 | 209800.000000 |
| 50% | 2020.0 | 19950.000000 | 103.000000 | 140.000000 | 227846.000000 |
| 75% | 2020.0 | 26000.000000 | 140.000000 | 190.000000 | 259000.000000 |
| max | 2020.0 | 44900.000000 | 255.000000 | 347.000000 | 435909.000000 |
Und was sind das für Autos?
autos_ab_200000km.head(10)
| Marke | Modell | Farbe | Erstzulassung | Jahr | Preis (Euro) | Leistung (kW) | Leistung (PS) | Getriebe | Kraftstoff | Verbrauch (l/100 km) | Verbrauch (g/km) | Kilometerstand (km) | Bemerkungen | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 968 | audi | Audi A6 | silber | 05/2020 | 2020 | 29100 | 170.0 | 231.0 | Automatik | Hybrid (Elektro/Diesel) | 5,9 l/100 km | 187 g/km | 215000.0 | Avant 45 TDI quattro sport |
| 1136 | audi | Audi S4 | weiß | 08/2020 | 2020 | 34990 | 255.0 | 347.0 | Automatik | Diesel | 6,3 l/100 km | 165 g/km | 227846.0 | Avant 3.0 TDI quattro Optik-Paket |
| 2265 | bmw | BMW 530 | weiß | 05/2020 | 2020 | 32999 | 195.0 | 265.0 | Automatik | Diesel | 5,9 l/100 km | 156 g/km | 209800.0 | Baureihe 5 Touring 530 d xDrive M Sport |
| 2340 | bmw | BMW 218 | orange | 08/2020 | 2020 | 27500 | 100.0 | 136.0 | Schaltgetriebe | Benzin | 6 l/100 km | - (g/km) | 290000.0 | 218i Coupe M Sport |
| 2726 | citroen | Citroen Jumper | weiß | 06/2020 | 2020 | 17999 | 103.0 | 140.0 | Schaltgetriebe | Diesel | NaN | - (g/km) | 273999.0 | L3 H4#Hoch/Lang#AT Motor erst 100.000km# |
| 2732 | citroen | Citroen Jumper | weiß | 09/2020 | 2020 | 19975 | 103.0 | 140.0 | Schaltgetriebe | Diesel | 6,5 l/100 km | 170 g/km | 215000.0 | 35 L4H2 Club Heavy BlueHD (AT Motor/Getr) |
| 2734 | citroen | Citroen Berlingo | weiß | 09/2020 | 2020 | 11781 | 56.0 | 76.0 | Schaltgetriebe | Diesel | 4,1 l/100 km | 109 g/km | 204377.0 | Kasten 1,5 BlueHDI Club M/L1 Klima Pdc |
| 2736 | citroen | Citroen Berlingo | weiß | 03/2020 | 2020 | 10980 | 75.0 | 102.0 | Schaltgetriebe | Diesel | 4 l/100 km | 106 g/km | 236400.0 | Kasten BlueHDi 100 Club M/L1 Kühlkasten |
| 2942 | dacia | Dacia Dokker | grau | 02/2020 | 2020 | 9500 | 70.0 | 95.0 | Schaltgetriebe | Diesel | 4,2 l/100 km | 111 g/km | 237420.0 | Express Comfort/1Hd./Scheckheftgepflegt |
| 3045 | dacia | Dacia Logan | silber | 03/2020 | 2020 | 9600 | 70.0 | 95.0 | Schaltgetriebe | Diesel | 3,6 l/100 km | 92 g/km | 217400.0 | MCV II Kombi Comfort Navi Standh. PDC 8-fach b... |
Mini-Übung
Filtern Sie den Datensatz so, dass nur Autos mit einem Preis zwischen
10.000 und 30.000 Euro übrig bleiben. Wie viele Autos erfüllen diese
Bedingung? Tipp: Sie können zwei Bedingungen mit & (und) verknüpfen.
Lösung
bedingung_preis = (data['Preis (Euro)'] >= 10000) & (data['Preis (Euro)'] <= 30000)
autos_mittlerer_preis = data[bedingung_preis]
print(f"Anzahl Autos: {len(autos_mittlerer_preis)}")
Es gibt 11.793 Autos in dieser Preisklasse.
Wichtig: Die Klammern um die einzelnen Bedingungen sind notwendig!
Daten gruppieren#
Eine Filterung nach Kilometerstand ermöglicht es uns, die Autos in zwei Datensätze zu teilen: Autos mit bis zu 200000 km Laufleistung und jene mit mehr als 200000 km (hierzu kann der Tilde-Operator (~) verwendet werden).
Wenden wir nun diese Technik an, um die Fahrzeuge basierend auf ihrer Marke zu trennen. Ein Beispiel: Um alle “Audi”-Fahrzeuge zu extrahieren, verwenden wir den folgenden Code:
bedingung_audi = data['Marke'] == 'audi'
audis = data[bedingung_audi]
audis.info()
<class 'pandas.core.frame.DataFrame'>
Index: 1190 entries, 104 to 1293
Data columns (total 14 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Marke 1190 non-null object
1 Modell 1190 non-null object
2 Farbe 1190 non-null object
3 Erstzulassung 1190 non-null object
4 Jahr 1190 non-null int64
5 Preis (Euro) 1190 non-null int64
6 Leistung (kW) 1189 non-null float64
7 Leistung (PS) 1189 non-null float64
8 Getriebe 1190 non-null object
9 Kraftstoff 1190 non-null object
10 Verbrauch (l/100 km) 1010 non-null object
11 Verbrauch (g/km) 1190 non-null object
12 Kilometerstand (km) 1190 non-null float64
13 Bemerkungen 1190 non-null object
dtypes: float64(3), int64(2), object(9)
memory usage: 139.5+ KB
Diese Bedingung erfüllen 1.190 Autos. Der Gesamtdatensatz enthält jedoch 41
unterschiedliche Automarken. Es wäre ineffizient, für jede Marke eine separate
Filterung durchzuführen. Deshalb bietet Pandas die .groupby()-Methode, die es
erlaubt, die Daten automatisch nach den einzigartigen Einträgen einer Spalte zu
gruppieren:
autos_nach_marke = data.groupby('Marke')
type(autos_nach_marke)
pandas.core.groupby.generic.DataFrameGroupBy
Das Resultat ist eine spezielle Pandas-Datenstruktur namens DataFrameGroupBy.
Auf dieses Objekt sind nicht alle bekannten DataFrame-Methoden anwendbar, aber
beispielsweise die .describe()-Methode darf verwendet werden:
autos_nach_marke.describe()
| Jahr | Preis (Euro) | ... | Leistung (PS) | Kilometerstand (km) | |||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| count | mean | std | min | 25% | 50% | 75% | max | count | mean | ... | 75% | max | count | mean | std | min | 25% | 50% | 75% | max | |
| Marke | |||||||||||||||||||||
| alfa-romeo | 88.0 | 2020.0 | 0.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 88.0 | 40263.840909 | ... | 280.00 | 510.0 | 88.0 | 40671.568182 | 24303.271950 | 1000.0 | 23475.00 | 36950.0 | 49743.75 | 121800.0 |
| aston-martin | 16.0 | 2020.0 | 0.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 16.0 | 174516.750000 | ... | 551.00 | 725.0 | 16.0 | 18923.250000 | 10374.581569 | 25.0 | 10965.00 | 19200.0 | 23942.00 | 42000.0 |
| audi | 1190.0 | 2020.0 | 0.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 1190.0 | 42584.115126 | ... | 310.00 | 810.0 | 1190.0 | 50733.891597 | 32154.868792 | 23.0 | 28500.00 | 42811.0 | 65000.00 | 227846.0 |
| bentley | 41.0 | 2020.0 | 0.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 41.0 | 239720.682927 | ... | 635.00 | 635.0 | 41.0 | 29706.804878 | 20568.477634 | 20.0 | 13500.00 | 26900.0 | 39900.00 | 93600.0 |
| bmw | 1039.0 | 2020.0 | 0.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 1039.0 | 38951.122233 | ... | 265.00 | 625.0 | 1039.0 | 51443.319538 | 33237.040181 | 57.0 | 27675.50 | 44500.0 | 67218.00 | 290000.0 |
| cadillac | 1.0 | 2020.0 | NaN | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 1.0 | 74900.000000 | ... | 426.00 | 426.0 | 1.0 | 51000.000000 | NaN | 51000.0 | 51000.00 | 51000.0 | 51000.00 | 51000.0 |
| chevrolet | 26.0 | 2020.0 | 0.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 26.0 | 42018.346154 | ... | 453.00 | 659.0 | 26.0 | 35102.769231 | 15601.368936 | 4000.0 | 21422.25 | 40258.0 | 43662.75 | 65505.0 |
| citroen | 446.0 | 2020.0 | 0.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 446.0 | 22244.840807 | ... | 140.00 | 299.0 | 446.0 | 45375.890135 | 36573.992887 | 10.0 | 22870.00 | 35000.0 | 56112.50 | 273999.0 |
| dacia | 268.0 | 2020.0 | 0.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 268.0 | 15726.611940 | ... | 131.00 | 150.0 | 268.0 | 38283.585821 | 28492.869299 | 2729.0 | 20300.00 | 33003.5 | 48292.25 | 237420.0 |
| dodge | 77.0 | 2020.0 | 0.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 77.0 | 52081.272727 | ... | 401.00 | 727.0 | 77.0 | 47216.012987 | 26368.755931 | 6300.0 | 26959.00 | 43097.0 | 64465.00 | 135200.0 |
| ferrari | 54.0 | 2020.0 | 0.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 54.0 | 391129.833333 | ... | 721.00 | 799.0 | 54.0 | 9954.703704 | 8160.580428 | 94.0 | 4165.25 | 7325.0 | 13242.00 | 33407.0 |
| fiat | 493.0 | 2020.0 | 0.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 493.0 | 16630.772819 | ... | 95.00 | 178.0 | 493.0 | 33325.330629 | 40859.386352 | 334.0 | 14900.00 | 22966.0 | 35540.00 | 399000.0 |
| ford | 1632.0 | 2020.0 | 0.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 1632.0 | 27152.117034 | ... | 190.00 | 771.0 | 1632.0 | 40053.620711 | 29541.064757 | 10.0 | 20895.00 | 33158.0 | 50000.00 | 275000.0 |
| honda | 68.0 | 2020.0 | 0.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 68.0 | 27821.191176 | ... | 184.00 | 320.0 | 68.0 | 32249.588235 | 18204.167592 | 6275.0 | 18337.50 | 27830.0 | 44491.75 | 87150.0 |
| hyundai | 431.0 | 2020.0 | 0.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 431.0 | 23627.011601 | ... | 179.00 | 275.0 | 431.0 | 36495.324826 | 21943.146134 | 700.0 | 21904.00 | 31850.0 | 46900.00 | 142215.0 |
| infiniti | 3.0 | 2020.0 | 0.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 3.0 | 30128.333333 | ... | 258.50 | 306.0 | 3.0 | 47491.666667 | 39365.402987 | 20000.0 | 24944.00 | 29888.0 | 61237.50 | 92587.0 |
| isuzu | 3.0 | 2020.0 | 0.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 3.0 | 43564.000000 | ... | 163.00 | 163.0 | 3.0 | 29081.333333 | 47560.960475 | 1622.0 | 1622.00 | 1622.0 | 42811.00 | 84000.0 |
| jaguar | 317.0 | 2020.0 | 0.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 317.0 | 41897.331230 | ... | 300.00 | 575.0 | 317.0 | 44402.170347 | 23793.378971 | 650.0 | 28890.00 | 41800.0 | 57200.00 | 143444.0 |
| jeep | 190.0 | 2020.0 | 0.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 190.0 | 36574.905263 | ... | 250.00 | 710.0 | 190.0 | 39909.336842 | 26124.141280 | 10.0 | 23000.00 | 33850.0 | 53025.00 | 149429.0 |
| kia | 491.0 | 2020.0 | 0.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 491.0 | 24249.158859 | ... | 200.00 | 370.0 | 491.0 | 42324.835031 | 25980.689971 | 4000.0 | 23695.00 | 35717.0 | 54278.50 | 254228.0 |
| lada | 7.0 | 2020.0 | 0.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 7.0 | 15404.857143 | ... | 102.00 | 106.0 | 7.0 | 18841.714286 | 9263.874760 | 35.0 | 19380.00 | 20000.0 | 21048.50 | 31000.0 |
| lamborghini | 50.0 | 2020.0 | 0.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 50.0 | 389851.860000 | ... | 650.00 | 770.0 | 50.0 | 19970.060000 | 22682.325994 | 292.0 | 4928.75 | 16977.5 | 28100.00 | 143000.0 |
| land-rover | 415.0 | 2020.0 | 0.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 415.0 | 53566.137349 | ... | 300.00 | 575.0 | 415.0 | 47685.327711 | 25125.806376 | 0.0 | 29597.50 | 42000.0 | 59900.00 | 144800.0 |
| maserati | 61.0 | 2020.0 | 0.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 61.0 | 89467.704918 | ... | 460.00 | 581.0 | 61.0 | 33712.180328 | 30107.363753 | 50.0 | 9900.00 | 24583.0 | 52534.00 | 150000.0 |
| mazda | 250.0 | 2020.0 | 0.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 250.0 | 25678.544000 | ... | 184.00 | 194.0 | 250.0 | 36376.016000 | 23666.670345 | 1000.0 | 19726.25 | 33023.0 | 46136.75 | 150000.0 |
| mercedes-benz | 1454.0 | 2020.0 | 0.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 1454.0 | 47093.824622 | ... | 286.00 | 700.0 | 1454.0 | 41981.423659 | 32327.716743 | 300.0 | 21052.50 | 34584.0 | 52000.00 | 435909.0 |
| mini | 621.0 | 2020.0 | 0.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 621.0 | 24969.685990 | ... | 192.00 | 306.0 | 621.0 | 35424.582931 | 17090.361947 | 1100.0 | 22900.00 | 32850.0 | 44873.00 | 98000.0 |
| mitsubishi | 105.0 | 2020.0 | 0.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 105.0 | 21177.552381 | ... | 150.00 | 224.0 | 105.0 | 37161.800000 | 23745.767214 | 2800.0 | 20604.00 | 30158.0 | 50857.00 | 92252.0 |
| nissan | 312.0 | 2020.0 | 0.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 312.0 | 25267.009615 | ... | 159.00 | 570.0 | 312.0 | 40053.500000 | 22080.302440 | 2000.0 | 25000.00 | 37000.0 | 49997.75 | 139870.0 |
| opel | 1538.0 | 2020.0 | 0.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 1538.0 | 20929.912874 | ... | 145.00 | 300.0 | 1538.0 | 38827.157347 | 26136.851607 | 15.0 | 21000.00 | 32000.0 | 49830.75 | 187340.0 |
| peugeot | 361.0 | 2020.0 | 0.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 361.0 | 24319.847645 | ... | 155.00 | 299.0 | 361.0 | 46022.229917 | 31726.338358 | 25.0 | 25000.00 | 40000.0 | 59500.00 | 323190.0 |
| porsche | 169.0 | 2020.0 | 0.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 169.0 | 120431.982249 | ... | 559.25 | 761.0 | 169.0 | 32106.573964 | 24197.348669 | 12.0 | 13774.00 | 29700.0 | 45217.00 | 168000.0 |
| renault | 558.0 | 2020.0 | 0.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 558.0 | 20071.415771 | ... | 150.00 | 300.0 | 558.0 | 41591.388889 | 35992.337097 | 20.0 | 20827.00 | 32035.0 | 47050.00 | 259000.0 |
| rover | 2.0 | 2020.0 | 0.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2.0 | 71770.000000 | ... | 363.25 | 404.0 | 2.0 | 49350.000000 | 4242.640687 | 46350.0 | 47850.00 | 49350.0 | 50850.00 | 52350.0 |
| seat | 1492.0 | 2020.0 | 0.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 1492.0 | 23371.157507 | ... | 150.00 | 300.0 | 1492.0 | 39579.088472 | 25351.928571 | 10.0 | 23493.25 | 34186.5 | 49302.50 | 234000.0 |
| skoda | 1518.0 | 2020.0 | 0.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 1518.0 | 25831.535573 | ... | 190.00 | 320.0 | 1518.0 | 51537.660079 | 34791.848676 | 10.0 | 27602.00 | 44688.0 | 68789.25 | 282000.0 |
| smart | 48.0 | 2020.0 | 0.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 48.0 | 15391.104167 | ... | 82.00 | 82.0 | 48.0 | 14515.062500 | 8497.519732 | 1064.0 | 8692.75 | 12050.0 | 20012.50 | 36360.0 |
| ssangyong | 17.0 | 2020.0 | 0.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 17.0 | 21770.352941 | ... | 163.00 | 181.0 | 17.0 | 38387.529412 | 25740.267049 | 11000.0 | 22955.00 | 33119.0 | 48000.00 | 107980.0 |
| toyota | 783.0 | 2020.0 | 0.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 783.0 | 24200.436782 | ... | 179.00 | 381.0 | 783.0 | 37311.786718 | 27091.019478 | 5.0 | 19628.00 | 31489.0 | 48484.50 | 255800.0 |
| volkswagen | 1359.0 | 2020.0 | 0.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 1359.0 | 28523.032377 | ... | 199.00 | 462.0 | 1359.0 | 44662.082414 | 31129.343058 | 50.0 | 23986.00 | 37000.0 | 56294.50 | 228336.0 |
| volvo | 572.0 | 2020.0 | 0.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 2020.0 | 572.0 | 41352.417832 | ... | 303.00 | 408.0 | 572.0 | 53661.150350 | 32460.347772 | 1246.0 | 32400.00 | 47682.0 | 66307.75 | 223000.0 |
41 rows × 40 columns
Für jede Automarke werden nun für jede Spalte mit numerischen Informationen die
statistischen Kennzahlen ermittelt. Die entstehende Tabelle ist etwas
unübersichtlich. Besser ist daher, sich die statistischen Kennzahlen einzeln
ausgeben zu lassen. Im Folgenden ermitteln wir die Mittelwerte der numerischen
Informationen nach Automarke. Ohne das Argument numeric_only=True würde Pandas
versuchen, auch die nicht-numerischen Spalten (wie ‘Marke’ oder ‘Farbe’) zu
mitteln, was zu einer Fehlermeldung führen würde. Mit diesem Argument wird die
Operation nur auf numerische Spalten angewendet.
durchschnittspreis_pro_marke = autos_nach_marke['Preis (Euro)'].mean()
# Visualisierung
import plotly.express as px
fig = px.bar(durchschnittspreis_pro_marke,
title='Durchschnittlicher Preis pro Automarke',
labels = {'value': 'Preis [EUR]'})
fig.show()
Eine sehr wichtige Methode der GroupBy-Datenstruktur ist die
get_group()-Methode. Damit können wir ein bestimmtes DataFrame-Objekt aus dem
GroupBy-Objekt extrahieren:
audis_alternativ = autos_nach_marke.get_group('audi')
audis_alternativ.info()
<class 'pandas.core.frame.DataFrame'>
Index: 1190 entries, 104 to 1293
Data columns (total 14 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Marke 1190 non-null object
1 Modell 1190 non-null object
2 Farbe 1190 non-null object
3 Erstzulassung 1190 non-null object
4 Jahr 1190 non-null int64
5 Preis (Euro) 1190 non-null int64
6 Leistung (kW) 1189 non-null float64
7 Leistung (PS) 1189 non-null float64
8 Getriebe 1190 non-null object
9 Kraftstoff 1190 non-null object
10 Verbrauch (l/100 km) 1010 non-null object
11 Verbrauch (g/km) 1190 non-null object
12 Kilometerstand (km) 1190 non-null float64
13 Bemerkungen 1190 non-null object
dtypes: float64(3), int64(2), object(9)
memory usage: 139.5+ KB
In der Variablen audis_alternativ steckt nun der gleiche Datensatz wie in der
Variablen audis, den wir bereits durch das Filtern des ursprünglichen
Datensatzes extrahiert haben. Beide Methoden führen zum gleichen Ergebnis. Die
Filterung mit Bedingungen ist direkter und oft intuitiver. Die Gruppierung mit
.groupby() und .get_group() ist besonders nützlich, wenn wir mehrere Gruppen
nacheinander untersuchen möchten, da wir die Gruppierung nur einmal durchführen
müssen.
Mini-Übung
Gruppieren Sie die Autos nach ‘Kraftstoff’ und berechnen Sie den durchschnittlichen Preis für jede Kraftstoffart. Welche Kraftstoffart ist im Durchschnitt am teuersten?
Lösung
autos_nach_kraftstoff = data.groupby('Kraftstoff')
durchschnittspreis = autos_nach_kraftstoff['Preis (Euro)'].mean()
print(durchschnittspreis.sort_values(ascending=False))
Die teuerste Kraftstoffart im Durchschnitt ist Hybrid (Elektro/Diesel). Einträge ohne Angabe vernachlässigen wir hier.
Wann filtern, wann gruppieren?#
Wir filtern, wenn wir einen Ausschnitt der Daten analysieren wollen. Zum Beispiel könnten wir nur die Audis untersuchen wollen. Das Ergebnis ist ein neuer DataFrame mit den gefilterten Zeilen. Wenn wir jedoch alle Kategorien vergleichen wollen, nutzen wir die Gruppierung. Beispielsweise könnten wir die Durchschnittpreise pro Marke berechnen wollen.
Beide Methoden können auch kombiniert werden. Wir können auch erst gruppieren
und dann eine spezifische Gruppe mit .get_group() extrahieren. Dies ist
besonders nützlich, wenn wir die Gruppierung für mehrere Analysen
wiederverwenden möchten.
Zusammenfassung und Ausblick#
In diesem Kapitel haben wir die Technik des Datenfilterns kennengelernt. Um
spezifische Einträge aus einem Datensatz basierend auf einem bestimmten Wert zu
extrahieren, nutzen wir Vergleichsoperationen und verwenden das resultierende
Series-Objekt als Index. Wenn das Ziel darin besteht, Daten anhand der
einzigartigen Werte einer Spalte zu gruppieren, dann ist die Kombination von
.groupby() und .get_group() oft der effizienteste Weg. Damit haben wir
unsere Einführung in die Datenexploration abgeschlossen, obwohl es noch viele
weitere Möglichkeiten gibt, die Daten zu erkunden. Im nächsten Kapitel beginnen
wir mit den Grundlagen des maschinellen Lernens und beschäftigen uns mit
Entscheidungsbäumen.